package com.hdmp.auth.aspect;

import com.google.common.collect.Lists;
import com.hdmp.auth.entity.SysOperationLogEntity;
import com.hdmp.auth.service.SysOperationLogService;
import com.hdmp.tool.util.HttpContextUtils;
import com.hdmp.tool.util.IPUtils;
import com.hdmp.tool.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author BigFan
 * @create 2018/11/17 2:18 PM
 */
@Aspect
@Component
@Slf4j
public class SysLogAspect {

    @Autowired
    SysOperationLogService sysOperationLogService;

    @Pointcut("@annotation(com.hdmp.auth.aspect.SysLog)")
    public void logPointCut() {

    }

    @AfterThrowing(pointcut = "logPointCut()", throwing = "ex")
    public void DoAfterThrowing(JoinPoint joinPoint, Throwable ex) {
        log.error("aspect 发现异常，异常恩嘻嘻为" + ex.getMessage(), ex);
        saveOperationLog(joinPoint, ex, null, null);

    }


    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("...............................$$$$$$$$$$$$$$$$");
        Date beginTime = new Date();
        Object result = joinPoint.proceed();
        Date endTime = new Date();
        Long executetime = endTime.getTime() - beginTime.getTime();
        saveOperationLog(joinPoint, null, beginTime, executetime);
        return result;

    }

    public void saveOperationLog(JoinPoint joinPoint, Throwable ex, Date beginTime, Long executeTime) {

        SysOperationLogEntity operationLogEntity = new SysOperationLogEntity();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SysLog sysLog = method.getAnnotation(SysLog.class);
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        Object[] args = joinPoint.getArgs();
        StringBuffer paramsBuffer = new StringBuffer();
        //是否修安排na
        if (sysLog.requestParam()) {
            // 获取参数的信息，传入到数据库中。
            Map<String, String[]> map = HttpContextUtils.getHttpServletRequest().getParameterMap();
            String requestParams = JsonUtils.toJson(map);
            operationLogEntity.setRequestParams(requestParams);
        }

        List<String> params = Lists.newArrayList();
        if (args != null && args.length > 0) {
            Arrays.stream(args).forEach(e -> {
                String param = JsonUtils.toJson(e);
                params.add(param);
            });


        }
        if (params.size() > 0) {
            operationLogEntity.setParams(StringUtils.join(params, ";"));
        }


        operationLogEntity.setMethod(className + "." + methodName + "()");
        operationLogEntity.setTitle(sysLog.title());
        operationLogEntity.setBeginTime(beginTime);
        operationLogEntity.setExecuteTime(executeTime);
        if (ex != null) {
            operationLogEntity.setStatus(SysOperationLogEntity.OPERATION_LOG_FAIL);
            operationLogEntity.setException(StringUtils.substring(ex.getMessage(), 0, 2000));
        }

        operationLogEntity.setOperateType(sysLog.logType().name());
        operationLogEntity.setOperateIp(IPUtils.getIpAddr(HttpContextUtils.getHttpServletRequest()));
        operationLogEntity.setRequestUri(HttpContextUtils.getHttpServletRequest().getRequestURI());

        sysOperationLogService.saveOrUpdate(operationLogEntity);
    }


}
